﻿using MQTTnet;
using MQTTnet.Client;
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Yb
{
    public class Mqtt
    {
        private IMqttClient _mqttClient;
        private MqttClientOptions _options;
        private string _server;
        private int _port;
        private string _username;
        private string _password;
        private string _clientId;

        // 定义事件
        public event Action OnOpen;                    // 连接成功
        public event Action<string> OnError;          // 错误信息
        public event Action OnClose;                  // 连接关闭
        public event Action<string, byte[]> OnMessage; // 收到消息（主题+内容）
        public event Action<bool> OnStateChange; // 连接状态变更事件：true=在线，false=离线

        /// <summary>
        /// 构造函数 - 初始化时设置连接参数
        /// </summary>
        /// <param name="server">服务器地址</param>
        /// <param name="port">端口号，默认1883</param>
        /// <param name="username">用户名</param>
        /// <param name="password">密码（可选）</param>
        /// <param name="clientId">客户端ID（可选，不提供则自动生成）</param>
        public Mqtt(string server, int port = 1883, string username = null, string password = null, string clientId = null)
        {
            _server = server;
            _port = port;
            _username = username;
            _password = password;
            _clientId = clientId ?? Guid.NewGuid().ToString().Substring(0, 8); // 默认生成简短ID

            InitializeMqttClient();
            BuildOptions();
        }

        /// <summary>
        /// 初始化MQTT客户端
        /// </summary>
        private void InitializeMqttClient()
        {
            var factory = new MqttFactory();
            _mqttClient = factory.CreateMqttClient();

            // 绑定MQTTnet客户端事件
            _mqttClient.ConnectedAsync += async e =>
            {
                OnOpen?.Invoke();
                OnStateChange?.Invoke(true);
                await Task.CompletedTask;
            };

            _mqttClient.DisconnectedAsync += async e =>
            {
                if (e.Exception != null)
                    OnError?.Invoke($"连接断开: {e.Exception.Message}");
                OnClose?.Invoke();
                OnStateChange?.Invoke(false);
                _ = Task.Run(async () =>
                {
                    try
                    {
                        await ReconnectAsync(maxRetryCount: 10, baseRetryInterval: 2000);
                    }
                    catch (Exception ex)
                    {
                        OnError?.Invoke($"自动重连过程中发生异常: {ex.Message}");
                    }
                });
                await Task.CompletedTask;
            };

            _mqttClient.ApplicationMessageReceivedAsync += async e =>
            {
                var topic = e.ApplicationMessage.Topic;
                var payload = e.ApplicationMessage.Payload;
                OnMessage?.Invoke(topic, payload);
                await Task.CompletedTask;
            };
            
        }

        /// <summary>
        /// 构建连接选项
        /// </summary>
        private void BuildOptions()
        {
            var builder = new MqttClientOptionsBuilder()
                .WithTcpServer(_server, _port)
                .WithClientId(_clientId)
                .WithCleanSession()
                .WithKeepAlivePeriod(TimeSpan.FromSeconds(60)) // 心跳间隔
                .WithTimeout(TimeSpan.FromSeconds(30)); // 超时时间

            // 添加用户名密码（如果提供用户名）
            if (!string.IsNullOrEmpty(_username))
            {
                builder.WithCredentials(_username, _password ?? "");
            }

            _options = builder.Build();
        }

        /// <summary>
        /// 连接到MQTT服务器
        /// </summary>
        public async Task ConnectAsync()
        {
            if (_mqttClient.IsConnected)
            {
                OnError?.Invoke("客户端已连接，无需重复连接");
                return;
            }

            try
            {
                await _mqttClient.ConnectAsync(_options, CancellationToken.None);
            }
            catch (Exception ex)
            {
                OnError?.Invoke($"连接失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 断开连接
        /// </summary>
        public async Task DisconnectAsync()
        {
            try
            {
                await _mqttClient.DisconnectAsync();
            }
            catch (Exception ex)
            {
                OnError?.Invoke($"断开连接失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 发送消息到指定主题
        /// </summary>
        public async Task SendAsync(string topic, byte[] payload, bool retain = false, MQTTnet.Protocol.MqttQualityOfServiceLevel qos = MQTTnet.Protocol.MqttQualityOfServiceLevel.AtMostOnce)
        {
            if (!_mqttClient.IsConnected)
            {
                OnError?.Invoke("客户端未连接");
                return;
            }

            try
            {
                var message = new MqttApplicationMessageBuilder()
                    .WithTopic(topic)
                    .WithPayload(payload)
                    .WithQualityOfServiceLevel(qos)
                    .WithRetainFlag(retain)
                    .Build();

                await _mqttClient.PublishAsync(message);
            }
            catch (Exception ex)
            {
                OnError?.Invoke($"发送消息失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 发送文本消息到指定主题
        /// </summary>
        public async Task SendStringAsync(string topic, string message, bool retain = false, MQTTnet.Protocol.MqttQualityOfServiceLevel qos = MQTTnet.Protocol.MqttQualityOfServiceLevel.AtMostOnce)
        {
            var payload = Encoding.UTF8.GetBytes(message);
            await SendAsync(topic, payload, retain, qos);
        }

        /// <summary>
        /// 订阅主题
        /// </summary>
        public async Task SubscribeAsync(string topic, MQTTnet.Protocol.MqttQualityOfServiceLevel qos = MQTTnet.Protocol.MqttQualityOfServiceLevel.AtMostOnce)
        {
            if (!_mqttClient.IsConnected)
            {
                OnError?.Invoke("客户端未连接");
                return;
            }

            try
            {
                await _mqttClient.SubscribeAsync(new MqttTopicFilterBuilder()
                    .WithTopic(topic)
                    .WithQualityOfServiceLevel(qos)
                    .Build());
            }
            catch (Exception ex)
            {
                OnError?.Invoke($"订阅失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 取消订阅
        /// </summary>
        public async Task UnsubscribeAsync(string topic)
        {
            if (!_mqttClient.IsConnected) return;

            try
            {
                await _mqttClient.UnsubscribeAsync(topic);
            }
            catch (Exception ex)
            {
                OnError?.Invoke($"取消订阅失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 更新连接参数（用于重连时使用新参数）
        /// </summary>
        public void UpdateConnectionParams(string server = null, int? port = null, string username = null, string password = null, string clientId = null)
        {
            _server = server ?? _server;
            _port = port ?? _port;
            _username = username ?? _username;
            _password = password ?? _password;
            _clientId = clientId ?? _clientId;

            BuildOptions(); // 重新构建选项
        }

        /// <summary>
        /// 实现断线重连机制
        /// </summary>
        public async Task ReconnectAsync(int maxRetryCount = 5, int baseRetryInterval = 1000)
        {
            int retryCount = 0;

            while (retryCount < maxRetryCount && !IsConnected)
            {
                try
                {
                    await _mqttClient.ConnectAsync(_options, CancellationToken.None);
                    if (IsConnected)
                    {
                        return;
                    }
                }
                catch (Exception ex)
                {
                    OnError?.Invoke($"重连尝试 {retryCount + 1}/{maxRetryCount} 失败: {ex.Message}");
                }

                retryCount++;
                int delay = baseRetryInterval * (int)Math.Pow(2, retryCount); // 指数退避
                await Task.Delay(delay);
            }

            if (!IsConnected)
            {
                OnError?.Invoke($"经过 {maxRetryCount} 次尝试后重连失败");
            }
        }

        /// <summary>
        /// 获取连接状态
        /// </summary>
        public bool IsConnected => _mqttClient?.IsConnected == true;

        /// <summary>
        /// 获取客户端ID
        /// </summary>
        public string ClientId => _clientId;

        /// <summary>
        /// 获取服务器地址
        /// </summary>
        public string Server => _server;

        /// <summary>
        /// 获取端口号
        /// </summary>
        public int Port => _port;
    }
}